//
// Created by martin on 2/5/22.
//

#ifndef MUDUO_ASYNCLOGGING_H
#define MUDUO_ASYNCLOGGING_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/Types.h"
#include "muduo/base/Thread.h"
#include "muduo/base/LogStream.h"
#include "muduo/base/Mutex.h"
#include "muduo/base/Condition.h"
#include "muduo/base/CountDownLatch.h"

#include <atomic>
#include <vector>
#include <memory>

namespace muduo
{

/**
 * Provide async logging function. backend.
 * Background thread (just only one) call this module to write log to file.
 */
class AsyncLogging : noncopyable
{
public:
    AsyncLogging(const string& basename,
                 off_t rollSize,
                 int flushInterval = 3);
    ~AsyncLogging()
    {
        if (running_)
        {
            stop();
        }
    }

    // Front threads append log message to current buffer.
    // Must be thread safe.
    void append(const char* logline, int len);

    // Control background thread

    void start()
    {
        running_ = true;
        thread_.start();
        latch_.wait();
    }

    void stop() NO_THREAD_SAFETY_ANALYSIS
    {
        running_ = false;
        cond_.notify();
        thread_.join();
    }

private:
    void threadFunc();

    typedef muduo::detail::FixedBuffer<muduo::detail::kLargeBuffer> Buffer;
    typedef std::vector<std::unique_ptr<Buffer>> BufferVector;
    typedef BufferVector::value_type BufferPtr;

    const int flushInterval_;
    std::atomic<bool> running_;
    const string basename_;
    const off_t rollSize_;
    muduo::Thread thread_;
    muduo::CountDownLatch latch_;
    muduo::MutexLock mutex_;
    muduo::Condition cond_ GUARDED_BY(mutex_);
    BufferPtr currentBuffer_ GUARDED_BY(mutex_);
    BufferPtr nextBuffer_ GUARDED_BY(mutex_);
    BufferVector buffers_ GUARDED_BY(mutex_);
};

} // namespace muduo

#endif //MUDUO_ASYNCLOGGING_H
